<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/9/1
 * Time: 16:39
 * from  http://www.webkaka.com/tutorial/php/2012/103026/
 */
//php实现限制文件下载速度的代码实例
//from http://www.webkaka.com/tutorial/php/2012/103026/
//有时候你会出于某种目的而要求把下载文件的速度放慢一些，例如你想实现文件下载进度条功能。限制下载速度最大的好处是节省带宽，避免瞬时流量过大而造成网络堵塞。本文将通过php代码来实现限制文件的下载速度。
$load_file = './aa.rar';// 将发送到客户端的本地文件
$down_file_name = time() . '.zip'; //// 文件名
$download_rate = 120.5;// 设置下载速率(=> 20,5 kb/s)
if (file_exists($load_file) && is_file($load_file)) {
    //发送header
    header('Cache-control:private');
    header('Content-Type: application/octet-stream');
    header("Accept-Ranges: bytes");
    header('Content-Length: ' . filesize($load_file));
    header('Content-Disposition:attachment; filename=' . $down_file_name);
    //flush 内容
    flush();
    //打开文件流
    $file = fopen($load_file, 'r');
    $already_file_size = 0;
    while (!feof($file) && $already_file_size < filesize($load_file)) {
        //发送当前部分文给浏览器
        print fread($file, round($download_rate * 1024));
        $already_file_size +=$download_rate * 1024;
        // flush 内容输出到浏览器端
        flush();

        //终端1秒后继续
        sleep(1);

    }
    //关闭文件流
    fclose($file);
} else {
    echo '文件不存在';

//    上述代码中，程序发送Header信息是用来告诉Apache和浏览器下载文件的相关信息的。content - type
//    的含义代表文件MIME类型是文件流格式。如果在Apache配置里面把文件的MIME类型设为
//    application / octet - stream（如add application / octet - stream . xxx . rar），
//    那么浏览器（客户端）就会知道，这是一个文件流格式的文件并提示用户下载。Accept - Ranges是一个响应头标，
//    它允许服务器指明将在给定的偏移和长度处，为资源组成部分的接受请求，
//    该头标的值被理解为请求范围的度量单位。Content - Length是指定包含于请求或响应中数据的字节长度，
//    例如，Content - Length:382。Content - Disposition:attachment是用来告诉浏览器，
//    文件是可以当做附件被下载，下载后的文件名称为$file_name该变量的值。

//    header("Content-type:text/html;charset=utf-8")的作用：在服务器响应浏览器的请求时，告诉浏览器以编码格式为UTF-8的编码显示该内容
//关于file_exists()函数不支持中文路径的问题:因为php函数比较早，不支持中文，所以如果被下载的文件名是中文的话，需要对其进行字符编码转换，否则file_exists()函数不能识别，可以使用iconv()函数进行编码转换
//$file_sub_path() 我使用的是绝对路径，执行效率要比相对路径高
//Header("Content-type: application/octet-stream")的作用：通过这句代码客户端浏览器就能知道服务端返回的文件形式
//Header("Accept-Ranges: bytes")的作用：告诉客户端浏览器返回的文件大小是按照字节进行计算的
//Header("Accept-Length:".$file_size)的作用：告诉浏览器返回的文件大小
//Header("Content-Disposition: attachment; filename=".$file_name)的作用:告诉浏览器返回的文件的名称
//以上四个Header()是必需的
//fclose($fp)可以把缓冲区内最后剩余的数据输出到磁盘文件中，并释放文件指针和有关的缓冲区
}